//
//  GCDQueueTableViewController.m
//  GCDDemo
//
//  Created by 苏沫离 on 2018/8/2.
//  Copyright © 2018年 苏沫离. All rights reserved.
//


#define CellIdentifer @"UITableViewCell"

#import "GCDQueueTableViewController.h"

@interface GCDQueueTableViewController ()
@property (nonatomic ,strong) NSArray<NSString *> *titleArray;
@end

@implementation GCDQueueTableViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifer];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.titleArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifer forIndexPath:indexPath];
    cell.textLabel.text = self.titleArray[indexPath.row];
    cell.textLabel.numberOfLines = 0;
    return cell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    NSLog(@"-------- 开始处理 --------");
    
    if (indexPath.row == 0)
    {
        [self dispatch_queue_serial_Method];
    }
    else if (indexPath.row == 1)
    {
        [self dispatch_queue_serial_inactive_Method];
    }
    else if (indexPath.row == 2)
    {
        [self dispatch_queue_concurrent_Method];
    }
    else if (indexPath.row == 3)
    {
        [self dispatch_queue_concurrent_inactive_Method];
    }
    else if (indexPath.row == 4)
    {
        [self dispatch_sync_Method];
    }
    else if (indexPath.row == 5)
    {
        [self dispatch_async_Method];
    }
    else if (indexPath.row == 6)
    {
        [self dispatch_async_f_Method];
    }
    else if (indexPath.row == 7)
    {
        [self dispatch_suspend_Method];
    }
    else if (indexPath.row == 8)
    {
        [self dispatch_serial_morequeue_Method];
    }
    else if (indexPath.row == 9)
    {
        [self dispatch_concurrent_morequeue_Method];
    }
    else if (indexPath.row == 10)
    {
        [self dispatch_set_target_queue_Method];
    }


    NSLog(@"-------- 结束处理 --------");
}

#pragma mark - dispatch_queue_attr_t

#pragma mark DISPATCH_QUEUE_SERIAL

- (void)dispatch_queue_serial_Method
{
    dispatch_queue_t queue = dispatch_queue_create("com.demo.serial", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(queue, ^{
        NSLog(@"开始执行：taskA ======= %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行：taskA ------- %@",NSThread.currentThread);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"开始执行：taskB ======= %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行：taskB ------- %@",NSThread.currentThread);
    });

    dispatch_async(queue, ^{
        NSLog(@"开始执行：taskC ======= %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行：taskC ------- %@",NSThread.currentThread);
    });
}

#pragma mark DISPATCH_QUEUE_SERIAL_INACTIVE

- (void)dispatch_queue_serial_inactive_Method
{
    if (@available(iOS 10.0, *))
    {
        //使用 DISPATCH_QUEUE_SERIAL_INACTIVE 创建的串行队列状态是不活跃的，在这个串行队列调用之前，必须使用dispatch_activate()函数激活队列
        dispatch_queue_t queue = dispatch_queue_create("com.demo.serial.inactive", DISPATCH_QUEUE_SERIAL_INACTIVE);
        
        dispatch_async(queue, ^{
            NSLog(@"开始执行：taskA ======= %@",NSThread.currentThread);
            [NSThread sleepForTimeInterval:3];//模拟耗时任务
            NSLog(@"结束执行：taskA ------- %@",NSThread.currentThread);
        });
        
        dispatch_async(queue, ^{
            NSLog(@"开始执行：taskB ======= %@",NSThread.currentThread);
            [NSThread sleepForTimeInterval:3];//模拟耗时任务
            NSLog(@"结束执行：taskB ------- %@",NSThread.currentThread);
        });
        
        dispatch_async(queue, ^{
            NSLog(@"开始执行：taskC ======= %@",NSThread.currentThread);
            [NSThread sleepForTimeInterval:3];//模拟耗时任务
            NSLog(@"结束执行：taskC ------- %@",NSThread.currentThread);
        });
    }
}

#pragma mark DISPATCH_QUEUE_CONCURRENT

- (void)dispatch_queue_concurrent_Method
{
    dispatch_queue_t queue = dispatch_queue_create("com.demo.concurrent", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        NSLog(@"开始执行：taskA ======= %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行：taskA ------- %@",NSThread.currentThread);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"开始执行：taskB ======= %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行：taskB ------- %@",NSThread.currentThread);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"开始执行：taskC ======= %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行：taskC ------- %@",NSThread.currentThread);
    });
}


#pragma mark DISPATCH_QUEUE_CONCURRENT_INACTIVE

- (void)dispatch_queue_concurrent_inactive_Method
{
    if (@available(iOS 10.0, *))
    {
        //使用DISPATCH_QUEUE_CONCURRENT_INACTIVE创建的并发队列状态是不活跃的，在这个并发队列调用之前，必须使用dispatch_activate()函数激活队列
        dispatch_queue_t queue = dispatch_queue_create("com.demo.concurrent.inactive", DISPATCH_QUEUE_CONCURRENT_INACTIVE);
        
        dispatch_activate(queue);
        
        dispatch_async(queue, ^{
            NSLog(@"开始执行：taskA ======= %@",NSThread.currentThread);
            [NSThread sleepForTimeInterval:3];//模拟耗时任务
            NSLog(@"结束执行：taskA ------- %@",NSThread.currentThread);
        });
        
        dispatch_async(queue, ^{
            NSLog(@"开始执行：taskB ======= %@",NSThread.currentThread);
            [NSThread sleepForTimeInterval:3];//模拟耗时任务
            NSLog(@"结束执行：taskB ------- %@",NSThread.currentThread);
        });
        
        dispatch_async(queue, ^{
            NSLog(@"开始执行：taskC ======= %@",NSThread.currentThread);
            [NSThread sleepForTimeInterval:3];//模拟耗时任务
            NSLog(@"结束执行：taskC ------- %@",NSThread.currentThread);
        });
    }
}

#pragma mark - 同步\异步执行

- (void)dispatch_sync_Method
{
    //创建一个并发队列
    dispatch_queue_t queue = dispatch_queue_create("com.demo.task", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{
        NSLog(@"开始执行：taskA ======= %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行：taskA ------- %@",NSThread.currentThread);
    });
    NSLog(@"------- 此处为taskA与taskB分界线 -------");
    dispatch_sync(queue, ^{
        NSLog(@"开始执行：taskB ======= %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行：taskB ------- %@",NSThread.currentThread);
    });
}

- (void)dispatch_async_Method
{
    dispatch_queue_t queue = dispatch_queue_create("com.demo.task", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        NSLog(@"开始执行：taskA ======= %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行：taskA ------- %@",NSThread.currentThread);
    });
    NSLog(@"------- 此处为taskA与taskB分界线 -------");
    dispatch_async(queue, ^{
        NSLog(@"开始执行：taskB ======= %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行：taskB ------- %@",NSThread.currentThread);
    });
}

#pragma mark - 任务函数

void dispatch_async_function_test(void *_Nullable context)
{
    id object = (__bridge id)context;
    NSLog(@"开始处理 ： %@ == %@",object,NSThread.currentThread);
    [NSThread sleepForTimeInterval:3];//模拟耗时任务
    NSLog(@"结束处理 ： %@ == %@",object,NSThread.currentThread);
}

- (void)dispatch_async_f_Method
{
    dispatch_queue_t queue = dispatch_queue_create("com.demo.task", DISPATCH_QUEUE_SERIAL);
    dispatch_async_f(queue, @"这是一个任意类型的参数", dispatch_async_function_test);
}

#pragma mark - 任务暂停/恢复操作

- (void)dispatch_suspend_Method
{
    dispatch_queue_t queue = dispatch_queue_create("com.demo.task", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(queue, ^{
        NSLog(@"开始执行taskA === %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行taskA === %@",NSThread.currentThread);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"开始执行taskB === %@",NSThread.currentThread);
        [NSThread sleepForTimeInterval:3];//模拟耗时任务
        NSLog(@"结束执行taskB === %@",NSThread.currentThread);
    });
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        dispatch_suspend(queue);
    });
    
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        dispatch_resume(queue);
    });
}

#pragma mark - 队列性能问题

/*
 
 
 */

- (void)dispatch_serial_morequeue_Method
{
    dispatch_apply(1000, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
        dispatch_queue_t queue = dispatch_queue_create("com.demo.task", DISPATCH_QUEUE_SERIAL);
        dispatch_async(queue, ^{
            NSLog(@"开始执行task%zu === %@",index,NSThread.currentThread);
            [NSThread sleepForTimeInterval:130];//模拟耗时任务
            NSLog(@"结束执行task%zu=== %@",index,NSThread.currentThread);
        });
    });
}


- (void)dispatch_concurrent_morequeue_Method
{
    dispatch_apply(1000, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
        dispatch_queue_t queue = dispatch_queue_create("com.demo.task", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
            NSLog(@"开始执行task%zu === %@",index,NSThread.currentThread);
            [NSThread sleepForTimeInterval:130];//模拟耗时任务
            NSLog(@"结束执行task%zu=== %@",index,NSThread.currentThread);
        });
    });
}

#pragma mark - 更改queue的优先级

/*
```dispatch_queue_create()```函数生成的队列```dispatch_queue```不管是串行队列```DISPATCH_QUEUE_SERIAL```，还是并发队列```DISPATCH_QUEUE_CONCURRENT```，都使用与默认优先级```DISPATCH_QUEUE_PRIORITY_DEFAULT```相同执行优先级的线程。而使用```dispatch_set_target_queue()```函数，可以改变```dispatch_queue_create()```函数生成队列```dispatch_queue```的优先级。
 
 ```dispatch_set_target_queue()```函数除了能用来设置队列的优先级之外，还能够创建队列的层次体系，当我们想让不同队列中的任务同步的执行时，我们可以创建一个串行队列，然后将这些队列的target指向新创建的队列即可，比如

 
 */

- (void)dispatch_set_target_queue_Method
{
    dispatch_queue_t queue = dispatch_queue_create("com.demo.task", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    
    
    //涉及到 GCD 队列与 block 的一个重要模型，target_queue：向任何队列中提交的 block，都会被放到它的目标队列中执行，而普通串行队列的目标队列就是一个支持 overcommit 的全局队列，全局队列的底层则是一个线程池。
    //更改目标队列 target_queue
    dispatch_set_target_queue(queue, global_queue);
    
    const char *lable = dispatch_queue_get_label(queue);
    NSLog(@"lable = %s",lable);
}

- (void)dispatch_set_target_queue_Method1
{

}

#pragma mark - setter and getter

- (NSArray<NSString *> *)titleArray
{
    if (_titleArray == nil)
    {
        _titleArray = @[@"DISPATCH_QUEUE_SERIAL",@"DISPATCH_QUEUE_SERIAL_INACTIVE",
                        @"DISPATCH_QUEUE_CONCURRENT",@"DISPATCH_QUEUE_CONCURRENT_INACTIVE",
                        @"dispatch_sync",@"dispatch_async",
                        @"dispatch_async_f",
                        @"dispatch_suspend",
                        @"串行队列性能问题", @"并发队列性能问题",
                        @"dispatch_set_target_queue"];
        
    }
    return _titleArray;
}


@end
